<template>
  <div class="vue-slider">
    <div class="slider-bar">
      <div class="slider-range">
        <input
          ref="range"
          type="range"
          v-model="rangeNum"
          :min="rangeMin"
          :max="rangeMax"
          :step="1"
        />
      </div>
      <div class="slider-mark">
        <div
          class="mark-num"
          v-for="(value, label) in marks"
          :key="value"
          :style="{
            width: markNumWidth + '%',
          }"
        >
          <span>{{ label }}</span>
        </div>
      </div>
    </div>
    <div class="slider-input">
      <input
        type="number"
        v-model="num"
        :min="min"
        :max="max"
        @blur="validateNull"
      />
      <span class="input-unit">{{ unit }}</span>
    </div>
  </div>
</template>

<script>
import _ from "lodash";

export default {
  name: "VueSlider",
  props: ["marks", "min", "max", "unit"],
  isFocus: false,
  data() {
    return {
      num: 1,
      rangeNum: 1,
      rangeMin: 1,
      rangeMax: this.max,
    };
  },
  mounted() {
    if (navigator.userAgent.toLowerCase().match(/chrome\/([\d.]+)/)) {
      this.$refs.range.style.background =
        "linear-gradient(to right, #337dff, #337dff 0%, #f2f2f2 0%)";
      this.$refs.range.style["border-radius"] = "10px";
    }
  },
  watch: {
    rangeNum(newValue) {
      var marks = _.keys(this.marks);
      var part = this.rangeMax / (marks.length - 1);
      var index = _.floor(newValue / part);
      var value = 0;

      if (index == 18) {
        value = marks[index];
      } else {
        var scale = (newValue - index * part) / part;
        value = _.round(
          marks[index] - 0 + scale * (marks[index + 1] - marks[index])
        );
      }

      if (
        _.max([value - 0, this.num - 0]) - _.min([value - 0, this.num - 0]) <=
        1
      ) {
        return;
      }
      this.num = value - 0;
      this.$emit("input", this.num);
      if (navigator.userAgent.toLowerCase().match(/chrome\/([\d.]+)/)) {
        this.$refs.range.style.background =
          "linear-gradient(to right, #337dff, #337dff " +
          (newValue / this.rangeMax) * 100 +
          "%, #f2f2f2 " +
          (newValue / this.rangeMax) * 100 +
          "%)";
      }
    },
    num(newValue) {
      var marks = _.keys(this.marks);
      var part = this.rangeMax / (marks.length - 1);
      var index = 0;
      if (newValue > marks[0]) {
        for (var i = 0; i < marks.length; i++) {
          if (newValue - 0 <= marks[i] - 0) {
            index = i - 1;
            break;
          }
        }
      }

      var diff = newValue - marks[index];
      var scale = diff / (marks[index + 1] - marks[index]);
      var val = _.round(index * part + scale * part);
      this.rangeNum = val;
      this.$emit("input", newValue);
      if (navigator.userAgent.toLowerCase().match(/chrome\/([\d.]+)/)) {
        this.$refs.range.style.background =
          "linear-gradient(to right, #337dff, #337dff " +
          (val / this.rangeMax) * 100 +
          "%, #f2f2f2 " +
          (val / this.rangeMax) * 100 +
          "%)";
      }
    },
  },
  computed: {
    markNumWidth: (vm) => 100 / (_.keys(vm.marks).length - 1),
  },
  methods: {
    validateNull() {
      if (!this.num) {
        this.num = this.min;
      }
    },
  },
};
</script>

<style lang="less">
.vue-slider {
  margin: 10px 0;

  .slider-bar {
    width: calc(100% - 240px);
    float: left;

    .slider-range {
      input[type="range"] {
        appearance: none;
        width: 100%;

        /* chrome轨道 */
        &::-webkit-slider-runnable-track {
          height: 10px;
          border-radius: 10px;
          -webkit-appearance: none;
        }
        /* chrome滑块 */
        &::-webkit-slider-thumb {
          -webkit-appearance: none;
          height: 18px;
          width: 18px;
          background: #ffffff;
          border-radius: 20px;
          border: solid 2px #337dff;
          margin-top: -4px;
        }

        //firefox滑条
        &::-moz-range-track {
          height: 10px;
          border-radius: 10px;
          outline: none;
          background-color: #f2f2f2;
        }

        //firefox滑块
        &::-moz-range-thumb {
          height: 15px;
          width: 15px;
          background: #ffffff;
          border-radius: 20px;
          border: solid 2px #337dff;
          margin-top: -7px;
        }
        //firefox滑条渐变
        &::-moz-range-progress {
          outline: none;
          height: 10px;
          background: linear-gradient(to right, #337dff, #337dff 100%, #f2f2f2);
          border-radius: 10px;
        }
        //ie滑条
        &::-ms-track {
          height: 10px;
          border-color: transparent;
          color: transparent;
          padding: 10px 0;
          background-color: #fff;
          appearance: none;
        }

        //ie滑条已填充部分
        &::-ms-fill-lower {
          border-radius: 10px;
          background: #337dff;
        }
        //ie滑条未填充部分
        &::-ms-fill-upper {
          border-radius: 10px;
          background: #f2f2f2;
        }

        //ie滑块
        &::-ms-thumb {
          height: 15px;
          width: 15px;
          background: #ffffff;
          border-radius: 20px;
          border: solid 2px #337dff;
          margin-top: 0px;
        }
      }
    }

    .slider-mark {
      margin-top: 7px;
      white-space: nowrap;
      padding: 0 7px;

      .mark-num {
        display: inline-block;
        font-size: 12px;
        color: #767676;
        position: relative;

        span {
          position: absolute;
          width: 50px;
          display: inline-block;
          left: -25px;
          top: -10px;
          text-align: center;
        }
      }

      .mark-num::before {
        content: " ";
        height: 10px;
        border-left: 1px solid #d9d9d9;
        position: absolute;
        top: -25px;
        left: 0;
      }
    }
  }
  .slider-input {
    width: 180px;
    display: inline-block;
    margin-left: 55px;

    input {
      width: 120px;
      text-align: left;
      padding: 0 5px;
      height: 30px;
    }
    input::-webkit-outer-spin-button,
    input::-webkit-inner-spin-button {
      -webkit-appearance: none;
    }
    input[type="number"] {
      -moz-appearance: textfield;
    }

    .input-unit {
      font-size: 12px;
      color: #6b6b6b;
      margin-left: 5px;
      width: 40px;
    }
  }
}
</style>
